🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / feature / messaging / src / commonMain / kotlin / org / meshtastic / feature / messaging / MessageViewModel.kt
Displaying Raw • Download
feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/MessageViewModel.kt f4506450168d047b225b277620bf0f1d5dcd13b5 (f4506450) Text, 18.91 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.messaging
Tff7b72import T7ee787androidx.lifecycle.SavedStateHandle
Tff7b72import T7ee787androidx.lifecycle.ViewModel
Tff7b72import T7ee787androidx.lifecycle.viewModelScope
Tff7b72import T7ee787androidx.paging.PagingData
Tff7b72import T7ee787androidx.paging.cachedIn
Tff7b72import T7ee787kotlinx.coroutines.FlowPreview
Tff7b72import T7ee787kotlinx.coroutines.Job
Tff7b72import T7ee787kotlinx.coroutines.delay
Tff7b72import T7ee787kotlinx.coroutines.flow.Flow
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.combine
Tff7b72import T7ee787kotlinx.coroutines.flow.debounce
Tff7b72import T7ee787kotlinx.coroutines.flow.emitAll
Tff7b72import T7ee787kotlinx.coroutines.flow.filterNotNull
Tff7b72import T7ee787kotlinx.coroutines.flow.flatMapLatest
Tff7b72import T7ee787kotlinx.coroutines.flow.flow
Tff7b72import T7ee787kotlinx.coroutines.flow.flowOf
Tff7b72import T7ee787kotlinx.coroutines.flow.update
Tff7b72import T7ee787kotlinx.coroutines.launch
Tff7b72import T7ee787org.koin.core.annotation.KoinViewModel
Tff7b72import T7ee787org.meshtastic.core.common.util.currentLocaleCode
Tff7b72import T7ee787org.meshtastic.core.common.util.ioDispatcher
Tff7b72import T7ee787org.meshtastic.core.model.ContactSettings
Tff7b72import T7ee787org.meshtastic.core.model.Message
Tff7b72import T7ee787org.meshtastic.core.model.Node
Tff7b72import T7ee787org.meshtastic.core.model.NodeAddress
Tff7b72import T7ee787org.meshtastic.core.repository.ConnectionStateProvider
Tff7b72import T7ee787org.meshtastic.core.repository.CustomEmojiPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.HomoglyphPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.MessagingController
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NotificationManager
Tff7b72import T7ee787org.meshtastic.core.repository.PacketRepository
Tff7b72import T7ee787org.meshtastic.core.repository.QuickChatActionRepository
Tff7b72import T7ee787org.meshtastic.core.repository.RadioConfigRepository
Tff7b72import T7ee787org.meshtastic.core.repository.UiPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.usecase.SendMessageUseCase
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.UiText
Tff7b72import T7ee787org.meshtastic.core.resources.translation_failed
Tff7b72import T7ee787org.meshtastic.core.resources.translation_model_download_failed
Tff7b72import T7ee787org.meshtastic.core.resources.translation_not_required
Tff7b72import T7ee787org.meshtastic.core.ui.util.SnackbarManager
Tff7b72import T7ee787org.meshtastic.core.ui.viewmodel.safeLaunch
Tff7b72import T7ee787org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
Tff7b72import T7ee787org.meshtastic.feature.messaging.translation.DownloadResult
Tff7b72import T7ee787org.meshtastic.feature.messaging.translation.MessageTranslationService
Tff7b72import T7ee787org.meshtastic.feature.messaging.translation.TranslationResult
Tff7b72import T7ee787org.meshtastic.proto.ChannelSet
T8b949e/**
* Test seam for resolving [UiText] to a plain string. Unit tests replace [resolve] so ViewModel snackbar paths don't
* depend on the compose-resources runtime (same pattern as NodeDetailUiTextResolver).
*/
Tff7b72internal Tff7b72object T56d364MessagingUiTextResolver Tb4b4b4{
Tff7b72var Te6edf3resolveTb4b4b4: Te6edf3suspend Tb4b4b4(Te6edf3UiTextTb4b4b4) Tff7b72-Tff7b72> Tffa657String Tff7b72= Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}
T8b949e/** State of the translation-model download dialog on the message screen. */
Tff7b72sealed Tff7b72interface T56d364TranslationDialogState Tb4b4b4{
Tff7b72data Tff7b72object T56d364Hidden Tb4b4b4: Te6edf3TranslationDialogState
T8b949e/** Ask the user to confirm downloading the missing [languageTags] models (~[estimatedSizeMb] MB). */
Tff7b72data Tff7b72class T56d364DownloadPromptTb4b4b4(Tff7b72val Te6edf3messageTb4b4b4: Te6edf3MessageTb4b4b4, Tff7b72val Te6edf3languageTagsTb4b4b4: Te6edf3ListTff7b72<Tffa657StringTff7b72>Tb4b4b4, Tff7b72val Te6edf3estimatedSizeMbTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4:
Te6edf3TranslationDialogState
Tff7b72data Tff7b72class T56d364DownloadingTb4b4b4(Tff7b72val Te6edf3messageTb4b4b4: Te6edf3MessageTb4b4b4) Tb4b4b4: Te6edf3TranslationDialogState
Tb4b4b4}
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongParameterListTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4)
Tf0883e@KoinViewModel
Tff7b72class T56d364MessageViewModelTb4b4b4(
Tff7b72private Tff7b72val Te6edf3savedStateHandleTb4b4b4: Te6edf3SavedStateHandleTb4b4b4,
Tff7b72private Tff7b72val Te6edf3nodeRepositoryTb4b4b4: Te6edf3NodeRepositoryTb4b4b4,
Te6edf3radioConfigRepositoryTb4b4b4: Te6edf3RadioConfigRepositoryTb4b4b4,
Te6edf3quickChatActionRepositoryTb4b4b4: Te6edf3QuickChatActionRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3connectionStateProviderTb4b4b4: Te6edf3ConnectionStateProviderTb4b4b4,
Tff7b72private Tff7b72val Te6edf3messagingControllerTb4b4b4: Te6edf3MessagingControllerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3packetRepositoryTb4b4b4: Te6edf3PacketRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3uiPrefsTb4b4b4: Te6edf3UiPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3customEmojiPrefsTb4b4b4: Te6edf3CustomEmojiPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3homoglyphEncodingPrefsTb4b4b4: Te6edf3HomoglyphPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3notificationManagerTb4b4b4: Te6edf3NotificationManagerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3sendMessageUseCaseTb4b4b4: Te6edf3SendMessageUseCaseTb4b4b4,
Tff7b72private Tff7b72val Te6edf3messageTranslationServiceTb4b4b4: Te6edf3MessageTranslationServiceTb4b4b4,
Tff7b72private Tff7b72val Te6edf3snackbarManagerTb4b4b4: Te6edf3SnackbarManagerTb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3ViewModelTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3_title Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3titleTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657StringTff7b72> Tff7b72= Te6edf3_titleTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_draftMessage Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3savedStateHandleTb4b4b4.Te6edf3getTff7b72<Tffa657StringTff7b72>Tb4b4b4(Ta5d6ff"Ta5d6ffdraftMessageTa5d6ff"Tb4b4b4) Tff7b72?: Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3draftMessageTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657StringTff7b72> Tff7b72= Te6edf3_draftMessageTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72var Te6edf3pendingDraftPersistenceTb4b4b4: Te6edf3Job? Tff7b72= Tff7b72null
T8b949e/**
* Updates the in-memory draft immediately. The durable [SavedStateHandle] write is debounced by
* [DRAFT_PERSISTENCE_DELAY_MS] — rapid edits cancel the prior pending flush, so only the trailing value persists.
* On process death within the debounce window the last ≤[DRAFT_PERSISTENCE_DELAY_MS] of typing is not durably
* saved; this is a conscious trade-off to avoid per-keystroke jank.
*/
Tff7b72fun Td2a8ffsetDraftMessageTb4b4b4(Te6edf3textTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Te6edf3_draftMessageTb4b4b4.Te6edf3value Tff7b72= Te6edf3text
Te6edf3pendingDraftPersistenceTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3pendingDraftPersistence Tff7b72=
Te6edf3viewModelScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Te6edf3delayTb4b4b4(Te6edf3DRAFT_PERSISTENCE_DELAY_MSTb4b4b4)
Te6edf3savedStateHandleTff7b72[Ta5d6ff"Ta5d6ffdraftMessageTa5d6ff"Tff7b72] Tff7b72= Te6edf3text
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffclearDraftMessageTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_draftMessageTb4b4b4.Te6edf3value Tff7b72= Ta5d6ff"Ta5d6ff"
Te6edf3pendingDraftPersistenceTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3pendingDraftPersistence Tff7b72= Tff7b72null
Te6edf3savedStateHandleTff7b72[Ta5d6ff"Ta5d6ffdraftMessageTa5d6ff"Tff7b72] Tff7b72= Ta5d6ff"Ta5d6ff"
Tb4b4b4}
Tff7b72val Te6edf3ourNodeInfo Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfo
Tff7b72val Te6edf3connectionState Tff7b72= Te6edf3connectionStateProviderTb4b4b4.Te6edf3connectionState
Tff7b72val Te6edf3nodeListTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ListTff7b72<Te6edf3NodeTff7b72>Tff7b72> Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3getNodesTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3channels Tff7b72= Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3channelSetFlowTb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3ChannelSetTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3showQuickChat Tff7b72= Te6edf3uiPrefsTb4b4b4.Te6edf3showQuickChat
Tff7b72val Te6edf3showFullMessageTimestamps Tff7b72= Te6edf3uiPrefsTb4b4b4.Te6edf3showFullMessageTimestamps
Tff7b72private Tff7b72val Te6edf3_showFiltered Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Tff7b72falseTb4b4b4)
Tff7b72val Te6edf3showFilteredTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3_showFilteredTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3quickChatActions Tff7b72= Te6edf3quickChatActionRepositoryTb4b4b4.Te6edf3getAllActionsTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3contactSettingsTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3MapTff7b72<Tffa657StringTb4b4b4, Te6edf3ContactSettingsTff7b72>Tff7b72> Tff7b72=
Te6edf3packetRepositoryTb4b4b4.Te6edf3getContactSettingsTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3emptyMapTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3contactKeyForPagedMessagesTb4b4b4: Te6edf3MutableStateFlowTff7b72<Tffa657String?Tff7b72> Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72private Tff7b72val Te6edf3pagedMessagesForContactKeyTb4b4b4: Te6edf3FlowTff7b72<Te6edf3PagingDataTff7b72<Te6edf3MessageTff7b72>Tff7b72> Tff7b72=
Te6edf3combineTb4b4b4(Te6edf3contactKeyForPagedMessagesTb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3_showFilteredTb4b4b4, Te6edf3contactSettingsTb4b4b4) Tb4b4b4{
Te6edf3contactKeyTb4b4b4,
Te6edf3showFilteredTb4b4b4,
Te6edf3settingsTb4b4b4,
Tff7b72-Tff7b72>
T8b949e// If filtering is disabled for this contact, always include filtered messages
Tff7b72val Te6edf3filteringDisabled Tff7b72= Te6edf3settingsTff7b72[Te6edf3contactKeyTff7b72]Tff7b72?.Te6edf3filteringDisabled Tff7b72?: Tff7b72false
Tff7b72val Te6edf3includeFiltered Tff7b72= Te6edf3showFiltered Tff7b72|Tff7b72| Te6edf3filteringDisabled
Te6edf3contactKey Te6edf3to Te6edf3includeFiltered
Tb4b4b4}
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Tb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3includeFilteredTb4b4b4) Tff7b72-Tff7b72>
Te6edf3packetRepositoryTb4b4b4.Te6edf3getMessagesFromPagedTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3includeFilteredTb4b4b4, Tff7b72::Te6edf3getNodeTb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3cachedInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Tff7b72val Te6edf3frequentEmojisTb4b4b4: Te6edf3ListTff7b72<Tffa657StringTff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72=
Te6edf3customEmojiPrefsTb4b4b4.Te6edf3customEmojiFrequencyTb4b4b4.Te6edf3value
Tff7b72?.Te6edf3splitTb4b4b4(Ta5d6ff"Ta5d6ff,Ta5d6ff"Tb4b4b4)
Tff7b72?.Te6edf3mapNotNull Tb4b4b4{ Te6edf3entry Tff7b72-Tff7b72>
Tff7b72val Te6edf3parts Tff7b72= Te6edf3entryTb4b4b4.Te6edf3splitTb4b4b4(Ta5d6ff"Ta5d6ff=Ta5d6ff"Tb4b4b4, Te6edf3limit Tff7b72= T79c0ff2Tb4b4b4)
Tff7b72val Te6edf3count Tff7b72= Te6edf3partsTb4b4b4.Te6edf3getOrNullTb4b4b4(T79c0ff1Tb4b4b4)Tff7b72?.Te6edf3toIntOrNullTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3partsTb4b4b4.Te6edf3size Tff7b72=Tff7b72= T79c0ff2 Tff7b72&Tff7b72& Te6edf3partsTff7b72[T79c0ff0Tff7b72]Tb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3count Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Te6edf3partsTff7b72[T79c0ff0Tff7b72] Te6edf3to Te6edf3count Tff7b72else Tff7b72null
Tb4b4b4}
Tff7b72?.Te6edf3sortedByDescending Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3second Tb4b4b4}
Tff7b72?.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3first Tb4b4b4}
Tff7b72?.Te6edf3takeTb4b4b4(T79c0ff6Tb4b4b4) Tff7b72?: Te6edf3listOfTb4b4b4(Ta5d6ff"Ta5d6ff👍Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff👎Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff😂Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff🔥Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff❤️Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff😮Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3homoglyphEncodingEnabled Tff7b72= Te6edf3homoglyphEncodingPrefsTb4b4b4.Te6edf3homoglyphEncodingEnabled
Tff7b72val Te6edf3firstUnreadMessageUuidTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657Long?Tff7b72> Tff7b72=
Te6edf3contactKeyForPagedMessages
Tb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3getFirstUnreadMessageUuidTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3hasUnreadMessagesTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657Boolean?Tff7b72> Tff7b72=
Te6edf3contactKeyForPagedMessages
Tb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3hasUnreadMessagesTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3unreadCountTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657IntTff7b72> Tff7b72=
Te6edf3contactKeyForPagedMessages
Tb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3getUnreadCountFlowTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72val Te6edf3filteredCountTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657IntTff7b72> Tff7b72=
Te6edf3contactKeyForPagedMessages
Tb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3getFilteredCountFlowTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(T79c0ff0Tb4b4b4)
T8b949e// region ── Search ──
Tff7b72private Tff7b72val Te6edf3_searchQuery Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3searchQueryTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657StringTff7b72> Tff7b72= Te6edf3_searchQueryTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_isSearchActive Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Tff7b72falseTb4b4b4)
Tff7b72val Te6edf3isSearchActiveTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3_isSearchActiveTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_searchResultIndex Tff7b72= Te6edf3MutableStateFlowTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72val Te6edf3searchResultIndexTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657IntTff7b72> Tff7b72= Te6edf3_searchResultIndexTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tf0883e@OptInTb4b4b4(Te6edf3FlowPreviewTff7b72::Te6edf3classTb4b4b4)
Tff7b72val Te6edf3searchResultsTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ListTff7b72<Te6edf3MessageTff7b72>Tff7b72> Tff7b72=
Te6edf3combineTb4b4b4(Te6edf3_searchQueryTb4b4b4, Te6edf3contactKeyForPagedMessagesTb4b4b4) Tb4b4b4{ Te6edf3queryTb4b4b4, Te6edf3contactKey Tff7b72-Tff7b72> Te6edf3query Te6edf3to Te6edf3contactKey Tb4b4b4}
Tb4b4b4.Te6edf3debounceTb4b4b4(Te6edf3SEARCH_DEBOUNCE_MSTb4b4b4)
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Tb4b4b4(Te6edf3queryTb4b4b4, Te6edf3contactKeyTb4b4b4) Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3queryTb4b4b4.Te6edf3length Tff7b72< Te6edf3MIN_SEARCH_LENGTHTb4b4b4) Tb4b4b4{
Te6edf3flowOfTb4b4b4(Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3packetRepositoryTb4b4b4.Te6edf3searchMessagesTb4b4b4(Te6edf3queryTb4b4b4, Te6edf3contactKeyTb4b4b4, Tff7b72::Te6edf3getNodeTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)
T8b949e/** The currently focused search result message (for scroll-to-match). */
Tff7b72val Te6edf3currentSearchResultTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3Message?Tff7b72> Tff7b72=
Te6edf3combineTb4b4b4(Te6edf3searchResultsTb4b4b4, Te6edf3_searchResultIndexTb4b4b4) Tb4b4b4{ Te6edf3resultsTb4b4b4, Te6edf3index Tff7b72-Tff7b72> Te6edf3resultsTb4b4b4.Te6edf3getOrNullTb4b4b4(Te6edf3indexTb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72fun Td2a8ffsetSearchQueryTb4b4b4(Te6edf3queryTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Te6edf3_searchQueryTb4b4b4.Te6edf3value Tff7b72= Te6edf3query
Te6edf3_searchResultIndexTb4b4b4.Te6edf3value Tff7b72= T79c0ff0
Tb4b4b4}
Tff7b72fun Td2a8ffnavigateToNextResultTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3max Tff7b72= Te6edf3searchResultsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3size
Tff7b72if Tb4b4b4(Te6edf3max Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72return
Te6edf3_searchResultIndexTb4b4b4.Te6edf3update Tb4b4b4{ Tb4b4b4(Tffa657it Tff7b72+ T79c0ff1Tb4b4b4) Tff7b72% Te6edf3max Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffnavigateToPreviousResultTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3max Tff7b72= Te6edf3searchResultsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3size
Tff7b72if Tb4b4b4(Te6edf3max Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72return
Te6edf3_searchResultIndexTb4b4b4.Te6edf3update Tb4b4b4{ Tff7b72if Tb4b4b4(Tffa657it Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Te6edf3max Tff7b72- T79c0ff1 Tff7b72else Tffa657it Tff7b72- T79c0ff1 Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8fftoggleSearchTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_isSearchActiveTb4b4b4.Te6edf3value Tff7b72= Tff7b72!Te6edf3_isSearchActiveTb4b4b4.Te6edf3value
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3_isSearchActiveTb4b4b4.Te6edf3valueTb4b4b4) Tb4b4b4{
Te6edf3_searchQueryTb4b4b4.Te6edf3value Tff7b72= Ta5d6ff"Ta5d6ff"
Te6edf3_searchResultIndexTb4b4b4.Te6edf3value Tff7b72= T79c0ff0
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffcloseSearchTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_isSearchActiveTb4b4b4.Te6edf3value Tff7b72= Tff7b72false
Te6edf3_searchQueryTb4b4b4.Te6edf3value Tff7b72= Ta5d6ff"Ta5d6ff"
Te6edf3_searchResultIndexTb4b4b4.Te6edf3value Tff7b72= T79c0ff0
Tb4b4b4}
T8b949e// endregion
Tff7b72init Tb4b4b4{
Tff7b72val Te6edf3contactKey Tff7b72= Te6edf3savedStateHandleTb4b4b4.Te6edf3getTff7b72<Tffa657StringTff7b72>Tb4b4b4(Ta5d6ff"Ta5d6ffcontactKeyTa5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3contactKey Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3contactKeyForPagedMessagesTb4b4b4.Te6edf3value Tff7b72= Te6edf3contactKey
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetContactKeyTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3contactKeyForPagedMessagesTb4b4b4.Te6edf3value Tff7b72!Tff7b72= Te6edf3contactKeyTb4b4b4) Tb4b4b4{
Te6edf3contactKeyForPagedMessagesTb4b4b4.Te6edf3value Tff7b72= Te6edf3contactKey
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetTitleTb4b4b4(Te6edf3titleTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Te6edf3_titleTb4b4b4.Te6edf3value Tff7b72= Te6edf3title
Tb4b4b4}
Tff7b72fun Td2a8ffgetMessagesFromPagedTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3FlowTff7b72<Te6edf3PagingDataTff7b72<Te6edf3MessageTff7b72>Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3contactKeyForPagedMessagesTb4b4b4.Te6edf3value Tff7b72!Tff7b72= Te6edf3contactKeyTb4b4b4) Tb4b4b4{
Te6edf3contactKeyForPagedMessagesTb4b4b4.Te6edf3value Tff7b72= Te6edf3contactKey
Tb4b4b4}
Tff7b72return Te6edf3pagedMessagesForContactKey
Tb4b4b4}
T8b949e/**
* Returns a non-paged reactive [Flow] of messages for a conversation. Used by desktop targets that don't use
* paging-compose.
*
* @param contactKey The unique contact key identifying the conversation.
* @param limit Optional maximum number of messages to return (null = all).
*/
Tff7b72fun Td2a8ffgetMessagesFlowTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3limitTb4b4b4: Tffa657Int? Tff7b72= Tff7b72nullTb4b4b4)Tb4b4b4: Te6edf3FlowTff7b72<Te6edf3ListTff7b72<Te6edf3MessageTff7b72>Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3contactKeyForPagedMessagesTb4b4b4.Te6edf3value Tff7b72!Tff7b72= Te6edf3contactKeyTb4b4b4) Tb4b4b4{
Te6edf3contactKeyForPagedMessagesTb4b4b4.Te6edf3value Tff7b72= Te6edf3contactKey
Tb4b4b4}
Tff7b72return Te6edf3flow Tb4b4b4{ Te6edf3emitAllTb4b4b4(Te6edf3packetRepositoryTb4b4b4.Te6edf3getMessagesFromTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3limit Tff7b72= Te6edf3limitTb4b4b4, Te6edf3getNode Tff7b72= Tff7b72::Te6edf3getNodeTb4b4b4)Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8fftoggleShowQuickChatTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3uiPrefsTb4b4b4.Te6edf3setShowQuickChatTb4b4b4(Tff7b72!Te6edf3uiPrefsTb4b4b4.Te6edf3showQuickChatTb4b4b4.Te6edf3valueTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8fftoggleShowFilteredTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_showFilteredTb4b4b4.Te6edf3update Tb4b4b4{ Tff7b72!Tffa657it Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsetContactFilteringDisabledTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3disabledTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3context Tff7b72= Te6edf3ioDispatcherTb4b4b4, Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetContactFilteringDisabledTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3packetRepositoryTb4b4b4.Te6edf3setContactFilteringDisabledTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3disabledTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffgetNodeTb4b4b4(Te6edf3userIdTb4b4b4: Tffa657String?Tb4b4b4) Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3getNodeTb4b4b4(Te6edf3userId Tff7b72?: Te6edf3NodeAddressTb4b4b4.Te6edf3ID_BROADCASTTb4b4b4)
Tff7b72fun Td2a8ffgetUserTb4b4b4(Te6edf3userIdTb4b4b4: Tffa657String?Tb4b4b4) Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3getUserTb4b4b4(Te6edf3userId Tff7b72?: Te6edf3NodeAddressTb4b4b4.Te6edf3ID_BROADCASTTb4b4b4)
T8b949e/**
* Sends a message to a contact or channel.
*
* If the message is a direct message (no channel specified), this function will:
* - If the device firmware version is older than 2.7.12, it will mark the destination node as a favorite to prevent
* it from being removed from the on-device node database.
* - If the device firmware version is 2.7.12 or newer, it will send a shared contact to the destination node.
*
* @param str The message content.
* @param contactKey The unique contact key, which is a combination of channel (optional) and node ID. Defaults to
* broadcasting on channel 0.
* @param replyId The ID of the message this is a reply to, if any.
*/
Tff7b72fun Td2a8ffsendMessageTb4b4b4(Te6edf3strTb4b4b4: Tffa657StringTb4b4b4, Te6edf3contactKeyTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ff0Tffd700${Te6edf3NodeAddressTb4b4b4.Te6edf3ID_BROADCASTTffd700}Ta5d6ff"Tb4b4b4, Te6edf3replyIdTb4b4b4: Tffa657Int? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsendMessageTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3sendMessageUseCaseTb4b4b4.Te6edf3invokeTb4b4b4(Te6edf3strTb4b4b4, Te6edf3contactKeyTb4b4b4, Te6edf3replyIdTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffsendReactionTb4b4b4(Te6edf3emojiTb4b4b4: Tffa657StringTb4b4b4, Te6edf3replyIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4) Tff7b72=
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsendReactionTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3messagingControllerTb4b4b4.Te6edf3sendReactionTb4b4b4(Te6edf3emojiTb4b4b4, Te6edf3replyIdTb4b4b4, Te6edf3contactKeyTb4b4b4) Tb4b4b4}
Tff7b72fun Td2a8ffdeleteMessagesTb4b4b4(Te6edf3uuidListTb4b4b4: Te6edf3ListTff7b72<Tffa657LongTff7b72>Tb4b4b4) Tff7b72=
Te6edf3safeLaunchTb4b4b4(Te6edf3context Tff7b72= Te6edf3ioDispatcherTb4b4b4, Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffdeleteMessagesTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3deleteMessagesTb4b4b4(Te6edf3uuidListTb4b4b4) Tb4b4b4}
T8b949e// region ── Translation ──
T8b949e/** Whether on-device translation into the current locale is possible (always false on F-Droid/desktop). */
Tff7b72val Te6edf3translationAvailableTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72=
Te6edf3flow Tb4b4b4{ Te6edf3emitTb4b4b4(Te6edf3messageTranslationServiceTb4b4b4.Te6edf3isLanguageAvailableTb4b4b4(Te6edf3currentLocaleCodeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Tff7b72falseTb4b4b4)
Tff7b72private Tff7b72val Te6edf3_translationDialogState Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3TranslationDialogStateTff7b72>Tb4b4b4(Te6edf3TranslationDialogStateTb4b4b4.Te6edf3HiddenTb4b4b4)
Tff7b72val Te6edf3translationDialogStateTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3TranslationDialogStateTff7b72> Tff7b72= Te6edf3_translationDialogStateTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
T8b949e/** Translates [message] into the device language, or just re-shows a previously persisted translation. */
T8b949e// Translation methods use plain safeLaunch (like sendMessage): every call inside is a main-safe suspend
T8b949e// function (the repository hops to IO internally), and tests stay on the deterministic test scheduler.
Tff7b72fun Td2a8fftranslateMessageTb4b4b4(Te6edf3messageTb4b4b4: Te6edf3MessageTb4b4b4) Tff7b72= Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6fftranslateMessageTa5d6ff"Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3messageTb4b4b4.Te6edf3translatedText Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3packetRepositoryTb4b4b4.Te6edf3setShowTranslatedTb4b4b4(Te6edf3messageTb4b4b4.Te6edf3uuidTb4b4b4, Tff7b72trueTb4b4b4)
Tff7b72returnTf0883e@safeLaunch
Tb4b4b4}
Tff7b72when Tb4b4b4(Tff7b72val Te6edf3result Tff7b72= Te6edf3messageTranslationServiceTb4b4b4.Te6edf3translateTb4b4b4(Te6edf3messageTb4b4b4.Te6edf3textTb4b4b4, Te6edf3currentLocaleCodeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72is Te6edf3TranslationResultTb4b4b4.Te6edf3Success Tff7b72-Tff7b72>
Te6edf3packetRepositoryTb4b4b4.Te6edf3setMessageTranslationTb4b4b4(Te6edf3messageTb4b4b4.Te6edf3uuidTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3translatedTextTb4b4b4)
Tff7b72is Te6edf3TranslationResultTb4b4b4.Te6edf3NotRequired Tff7b72-Tff7b72>
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(
Te6edf3MessagingUiTextResolverTb4b4b4.Te6edf3resolveTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3translation_not_requiredTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72is Te6edf3TranslationResultTb4b4b4.Te6edf3ModelDownloadRequired Tff7b72-Tff7b72>
Te6edf3_translationDialogStateTb4b4b4.Te6edf3value Tff7b72=
Te6edf3TranslationDialogStateTb4b4b4.Te6edf3DownloadPromptTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3languageTagsTb4b4b4, Te6edf3resultTb4b4b4.Te6edf3estimatedSizeMbTb4b4b4)
Tff7b72is Te6edf3TranslationResultTb4b4b4.Te6edf3Unavailable Tff7b72-Tff7b72>
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(
Te6edf3MessagingUiTextResolverTb4b4b4.Te6edf3resolveTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3translation_failedTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8fftoggleShowTranslatedTb4b4b4(Te6edf3messageTb4b4b4: Te6edf3MessageTb4b4b4) Tff7b72= Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6fftoggleShowTranslatedTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3packetRepositoryTb4b4b4.Te6edf3setShowTranslatedTb4b4b4(Te6edf3messageTb4b4b4.Te6edf3uuidTb4b4b4, Tff7b72!Te6edf3messageTb4b4b4.Te6edf3showTranslatedTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffconfirmTranslationModelDownloadTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3prompt Tff7b72= Te6edf3_translationDialogStateTb4b4b4.Te6edf3value Tff7b72as? Te6edf3TranslationDialogStateTb4b4b4.Te6edf3DownloadPrompt Tff7b72?: Tff7b72return
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffdownloadTranslationModelTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3_translationDialogStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3TranslationDialogStateTb4b4b4.Te6edf3DownloadingTb4b4b4(Te6edf3promptTb4b4b4.Te6edf3messageTb4b4b4)
Tff7b72val Te6edf3result Tff7b72= Te6edf3messageTranslationServiceTb4b4b4.Te6edf3downloadLanguageModelsTb4b4b4(Te6edf3promptTb4b4b4.Te6edf3languageTagsTb4b4b4)
Te6edf3_translationDialogStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3TranslationDialogStateTb4b4b4.Te6edf3Hidden
Tff7b72when Tb4b4b4(Te6edf3resultTb4b4b4) Tb4b4b4{
Tff7b72is Te6edf3DownloadResultTb4b4b4.Te6edf3Success Tff7b72-Tff7b72> Te6edf3translateMessageTb4b4b4(Te6edf3promptTb4b4b4.Te6edf3messageTb4b4b4)
Tff7b72is Te6edf3DownloadResultTb4b4b4.Te6edf3Failed Tff7b72-Tff7b72>
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(
Te6edf3MessagingUiTextResolverTb4b4b4.Te6edf3resolveTb4b4b4(Te6edf3UiTextTb4b4b4.Te6edf3ResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3translation_model_download_failedTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffdismissTranslationDialogTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_translationDialogStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3TranslationDialogStateTb4b4b4.Te6edf3Hidden
Tb4b4b4}
T8b949e// endregion
Tff7b72fun Td2a8ffclearUnreadCountTb4b4b4(Te6edf3contactTb4b4b4: Tffa657StringTb4b4b4, Te6edf3messageUuidTb4b4b4: Tffa657LongTb4b4b4, Te6edf3lastReadTimestampTb4b4b4: Tffa657LongTb4b4b4) Tff7b72=
Te6edf3safeLaunchTb4b4b4(Te6edf3context Tff7b72= Te6edf3ioDispatcherTb4b4b4, Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffclearUnreadCountTa5d6ff"Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3existingTimestamp Tff7b72= Te6edf3contactSettingsTb4b4b4.Te6edf3valueTff7b72[Te6edf3contactTff7b72]Tff7b72?.Te6edf3lastReadMessageTimestamp Tff7b72?: Tffa657LongTb4b4b4.Te6edf3MIN_VALUE
Tff7b72if Tb4b4b4(Te6edf3lastReadTimestamp Tff7b72<Tff7b72= Te6edf3existingTimestampTb4b4b4) Tb4b4b4{
Tff7b72returnTf0883e@safeLaunch
Tb4b4b4}
Te6edf3packetRepositoryTb4b4b4.Te6edf3clearUnreadCountTb4b4b4(Te6edf3contactTb4b4b4, Te6edf3lastReadTimestampTb4b4b4)
Te6edf3packetRepositoryTb4b4b4.Te6edf3updateLastReadMessageTb4b4b4(Te6edf3contactTb4b4b4, Te6edf3messageUuidTb4b4b4, Te6edf3lastReadTimestampTb4b4b4)
Tff7b72val Te6edf3unreadCount Tff7b72= Te6edf3packetRepositoryTb4b4b4.Te6edf3getUnreadCountTb4b4b4(Te6edf3contactTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3unreadCount Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3contactTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72private Tff7b72const Tff7b72val Te6edf3SEARCH_DEBOUNCE_MS Tff7b72= T79c0ff3T79c0ff0T79c0ff0L
Tff7b72private Tff7b72const Tff7b72val Te6edf3MIN_SEARCH_LENGTH Tff7b72= T79c0ff2
Tff7b72private Tff7b72const Tff7b72val Te6edf3DRAFT_PERSISTENCE_DELAY_MS Tff7b72= T79c0ff3T79c0ff0T79c0ff0L
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.12s